#!perl
# google-video-psp: 
#   Sync Google Video files in a folder to PSP automatically

use strict;
use Digest::MD5;
use File::Copy;
use FindBin;
use File::Spec::Functions qw(catfile);
use YAML;

our $datafile = 'google-video-psp.txt';

my $file = catfile($FindBin::Bin, 'google-video-psp.yaml');
my $cfg  = YAML::LoadFile($file);

-e $cfg->{psp_dir} && -d _
    or die "PSP might not be connected. $cfg->{psp_dir}: $!";
my $synced_files = synced_files($cfg->{psp_dir});

my $sync_dir = $cfg->{sync_dir};
opendir DIR, $sync_dir or die "$sync_dir: $!";
while (my $f = readdir DIR) {
    my $file = catfile($sync_dir, $f);
    next unless -f $file && $file =~ /\.(?:MP4|THM)$/i;
    my $md5 = get_md5($file);
    unless ($synced_files->{$md5}++) {
        do_copy($f, $file, $cfg);
    }
}

flush_synced($cfg->{psp_dir}, $synced_files);

sub do_copy {
    my($f, $file, $cfg) = @_;
    my $dest = gen_dest($f, $cfg);
    warn "copying $file -> $dest\n";
    copy($file, $dest);
}

sub gen_dest {
    my($f, $cfg) = @_;
    if ($f =~ /MAQ\d{5}\.(?:MP4|THM)$/i) {
        return catfile($cfg->{psp_dir}, $f);
    }
    my $try;
    my $dest;
    while ($try++ <= 10) {
        $dest = sprintf 'MAQ%05d.MP4', rand(100000);
        $dest = catfile($cfg->{psp_dir}, $dest);
        last unless -e $dest;
    }
    $dest;
}

sub get_md5 {
    my $file = shift;
    my $md5 = Digest::MD5->new;
    open my $fh, $file or die "$file: $!";
    $md5->addfile($fh);
    return $md5->hexdigest;
}

sub synced_files {
    my $psp_dir = shift;
    my $file = catfile($psp_dir, $datafile);
    open my $fh, $file
        or return scan_mp4_files($psp_dir);
    my $synced = {};
    while (<$fh>) {
        chomp;
        $synced->{$_} = 1;
    }
    $synced;
}

sub scan_mp4_files {
    my $psp_dir = shift;
    my $files;
    opendir DIR, $psp_dir or die $!;
    while (my $f = readdir DIR) {
        my $mp4 = catfile($psp_dir, $f);
        next unless -f $mp4 && $mp4 =~ /\.(?:MP4|THM)$/i;
	warn "scanning MD5 of $mp4\n";
        $files->{get_md5($mp4)} = 1;
    }
    $files;
}

sub flush_synced {
    my($psp_dir, $keys) = @_;
    open my $fh, '>', catfile($psp_dir, $datafile) or die $!;
    for my $md5 (keys %$keys) {
        print $fh "$md5\n";
    }
}
